// eslint-disable-next-line no-restricted-imports
import type { Ref } from 'vue';
import { unref } from 'vue';

import { getCurrentScope, onScopeDispose } from 'vue';

export type Fn = () => void;
/**
 * Any function
 */
export type AnyFn = (...args: any[]) => any;

/**
 * Maybe it's a ref, or a plain value
 *
 * ```ts
 * type MaybeRef<T> = T | Ref<T>
 * ```
 */
export type MaybeRef<T> = T | Ref<T>;
/**
 * Maybe it's a ref, or a plain value, or a getter function
 *
 * ```ts
 * type MaybeRefOrGetter<T> = (() => T) | T | Ref<T> | ComputedRef<T>
 * ```
 */
export type MaybeRefOrGetter<T> = MaybeRef<T> | (() => T);

export const isClient =
  typeof window !== 'undefined' && typeof document !== 'undefined';
export const isObject = (val: any): val is object =>
  toString.call(val) === '[object Object]';
export const noop = () => {};

/**
 * Call onScopeDispose() if it's inside an effect scope lifecycle, if not, do nothing
 *
 * @param fn
 */
export function tryOnScopeDispose(fn: Fn) {
  if (getCurrentScope()) {
    onScopeDispose(fn);
    return true;
  }
  return false;
}

/**
 * Get the value of value/ref/getter.
 */
export function toValue<T>(r: MaybeRefOrGetter<T>): T {
  return typeof r === 'function' ? (r as AnyFn)() : unref(r);
}

/**
 * @deprecated use `toValue` instead
 */
export const resolveUnref = toValue;
